home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 23 / AACD 23.iso / AACD / Online / opennap / whois.c < prev    next >
C/C++ Source or Header  |  2001-06-08  |  7KB  |  294 lines

  1. /* Copyright (C) 2000-1 drscholl@users.sourceforge.net
  2.    This is free software distributed under the terms of the
  3.    GNU Public License.  See the file COPYING for details.
  4.  
  5.    $Id: whois.c,v 1.59 2001/02/15 08:39:45 drscholl Exp $ */
  6.  
  7. #include <stdio.h>
  8. #include <time.h>
  9. #include <string.h>
  10. #include <stdlib.h>
  11. #include "opennap.h"
  12. #include "debug.h"
  13.  
  14. /* this is nasty but a necessary evil to avoid using a static buffer */
  15. char   *
  16. append_string (char *in, const char *fmt, ...)
  17. {
  18.     va_list ap;
  19.  
  20.     va_start (ap, fmt);
  21.     vsnprintf (Buf, sizeof (Buf), fmt, ap);
  22.     va_end (ap);
  23.     if (!in)
  24.     return STRDUP (Buf);
  25.     else
  26.     {
  27.     int     len = strlen (in);
  28.  
  29.     if (safe_realloc ((void **) &in, len + strlen (Buf) + 1))
  30.         return 0;
  31.     strcpy (in + len, Buf);
  32.     return in;
  33.     }
  34. }
  35.  
  36. /* 604 <user> */
  37. HANDLER (whois)
  38. {
  39.     USER   *sender, *user;
  40.     time_t  online;
  41.     LIST   *chan;
  42.     USERDB *db;
  43.     char   *cap;
  44.     char   *rsp = 0;
  45.     char   *nick;
  46.  
  47.     (void) tag;
  48.     (void) len;
  49.     CHECK_USER_CLASS ("whois");
  50.     sender = con->user;
  51.     ASSERT (validate_connection (con));
  52.     nick = next_arg (&pkt);
  53.     if (!nick)
  54.     {
  55.     send_cmd (con, MSG_SERVER_NOSUCH, "whois failed: missing nickname");
  56.     return;
  57.     }
  58.     user = hash_lookup (Users, nick);
  59.     if (!user)
  60.     {
  61.     /* check to see if this is a registered nick */
  62.     db = hash_lookup (User_Db, nick);
  63.     if (db)
  64.         send_cmd (con, MSG_SERVER_WHOWAS, "%s \"%s\" %u", db->nick,
  65.               Levels[db->level], db->lastSeen);
  66.     else
  67.         send_cmd (con, MSG_SERVER_NOSUCH,
  68.               "user %s is not a known user", nick);
  69.     nosuchuser (con);
  70.     return;
  71.     }
  72.  
  73.     ASSERT (validate_user (user));
  74.  
  75.     online = (int) (global.current_time - user->connected);
  76.  
  77.     rsp = append_string (rsp, "%s", user->nick);
  78.     rsp = append_string (rsp, " \"%s\"", Levels[user->level]);
  79.     rsp = append_string (rsp, " %u", (int) online);
  80.     rsp = append_string (rsp, " \" ");
  81.     /* always show channel membership to privileged users */
  82.     if (!user->cloaked || sender->level > LEVEL_USER)
  83.     {
  84.     for (chan = user->channels; chan; chan = chan->next)
  85.     {
  86.         if ((((CHANNEL *) chan->data)->flags & ON_CHANNEL_PRIVATE) == 0)
  87.         rsp =
  88.             append_string (rsp, "%s ",
  89.                    ((CHANNEL *) chan->data)->name);
  90.     }
  91.     }
  92.     rsp = append_string (rsp, "\"");    /* terminate the channel list */
  93.  
  94.     if (user->muzzled)
  95.     cap = "Muzzled";
  96.     else if (user->cloaked && sender->level > LEVEL_USER)
  97.     cap = "Cloaked";    /* show cloaked state to privileged users */
  98.     else
  99.     cap = "Active";
  100.     rsp = append_string (rsp, " \"%s\"", cap);
  101.     rsp = append_string (rsp, " %d %d %d %d", user->shared, user->downloads,
  102.              user->uploads, user->speed);
  103.     rsp = append_string (rsp, " \"%s\"", user->clientinfo);
  104.  
  105.     /* moderators and above see some additional information */
  106.     if (sender->level > LEVEL_USER)
  107.     {
  108.     db = hash_lookup (User_Db, user->nick);
  109.     rsp = append_string (rsp, " %d %d %s %hu %hu",
  110.                  user->totaldown, user->totalup,
  111.                  my_ntoa (BSWAP32 (user->ip)),
  112.                  user->conport, user->port);
  113. #if EMAIL
  114. #define EmailAddr(db) db?db->email:"unknown"
  115. #else
  116. #define EmailAddr(db) "unknown"
  117. #endif
  118.     rsp = append_string (rsp, " %s", EmailAddr (db));
  119.     }
  120.     /* admins and above see the server the user is connected to.  this is
  121.        only admin+ since the windows client would likely barf if present.
  122.        i assume that admin+ will use another client such as BWap which
  123.        understands the extra field */
  124.     if (sender->level > LEVEL_MODERATOR)
  125.     rsp =
  126.         append_string (rsp, " %s",
  127.                user->server ? user->server : Server_Name);
  128.     send_user (sender, MSG_SERVER_WHOIS_RESPONSE, "%s", rsp);
  129.     FREE (rsp);
  130.  
  131.     /* notify privileged users when someone requests their info */
  132.     if (user->level >= LEVEL_MODERATOR && sender != user)
  133.     {
  134.     ASSERT (validate_connection (user->con));
  135.  
  136.     if (ISUSER (user->con))
  137.     {
  138.         if (user->con->uopt->usermode & WHOISLOG_MODE)
  139.         send_cmd (user->con, MSG_SERVER_NOSUCH,
  140.               "%s has requested your info", con->user->nick);
  141.     }
  142.     else
  143.     {
  144.         /* relay the whois notifcation to the target's server.  doing
  145.          * this as a separate message allows us to do a usermode -whois
  146.          * to turn off this messge if the user doesn't care to see it.
  147.          */
  148.         send_cmd (user->con, MSG_SERVER_WHOIS_NOTIFY, ":%s %s",
  149.               con->user->nick, user->nick);
  150.     }
  151.     }
  152. }
  153.  
  154. /* 10024 :<sender> <nick>
  155.  * remote whois notification
  156.  */
  157. HANDLER (whois_notify)
  158. {
  159.     char   *sender_name;
  160.     USER   *sender;
  161.     USER   *target;
  162.     char   *nick;
  163.  
  164.     (void) len;
  165.     CHECK_SERVER_CLASS("whois_notify");
  166.     if (pop_user_server (con, tag, &pkt, &sender_name, &sender))
  167.     return;
  168.     nick = next_arg (&pkt);
  169.     if (!nick)
  170.     {
  171.     log ("whois_notify: missing argument");
  172.     return;
  173.     }
  174.     target = hash_lookup (Users, nick);
  175.     if (!target)
  176.     {
  177.     log ("whois_notify: %s: no such user", nick);
  178.     return;
  179.     }
  180.     if (ISUSER (target->con))
  181.     {
  182.     if (target->con->uopt->usermode & WHOISLOG_MODE)
  183.         send_cmd (target->con, MSG_SERVER_NOSUCH,
  184.               "%s has requested your info", sender_name);
  185.     }
  186.     else
  187.     send_cmd (target->con, tag, ":%s %s", sender_name, target->nick);
  188. }
  189.  
  190. /* 10119 <user>
  191.  * display which server a particular user is on
  192.  */
  193. HANDLER (which_server)
  194. {
  195.     USER   *user;
  196.     char   *nick;
  197.  
  198.     (void) tag;
  199.     (void) len;
  200.     CHECK_USER_CLASS ("which_server");
  201.     /* leeches are bad, mmmkay? */
  202.     if (con->user->level < LEVEL_USER)
  203.     {
  204.     send_cmd (con, MSG_SERVER_ERROR,
  205.           "which server failed: permission denied");
  206.     return;
  207.     }
  208.     nick = next_arg (&pkt);
  209.     if (!nick)
  210.     {
  211.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  212.           "which server failed: missing nick");
  213.     return;
  214.     }
  215.     user = hash_lookup (Users, nick);
  216.     if (!user)
  217.     {
  218.     send_cmd (con, MSG_SERVER_NOSUCH,
  219.           "which server failed: no such user");
  220.     return;
  221.     }
  222.     if (ISUSER (user->con))
  223.     send_cmd (con, MSG_SERVER_NOSUCH, "%s is on %s", user->nick,
  224.           user->server);
  225.     else
  226.     send_cmd (con, MSG_SERVER_NOSUCH, "%s is on %s (via %s)", user->nick,
  227.           user->server, user->con->host);
  228. }
  229.  
  230. /* 10121 <user>
  231.  * who-was
  232.  */
  233. HANDLER (who_was)
  234. {
  235.     char   *nick = next_arg (&pkt);
  236.     whowas_t *who;
  237.  
  238.     (void) len;
  239.     CHECK_USER_CLASS ("who_was");
  240.     if (!nick)
  241.     {
  242.     send_cmd (con, MSG_SERVER_NOSUCH, "who was failed: missing nickname");
  243.     return;
  244.     }
  245.     if (con->user->level < LEVEL_MODERATOR)
  246.     {
  247.     send_cmd (con, MSG_SERVER_NOSUCH,
  248.           "who was failed: permission denied");
  249.     return;
  250.     }
  251.     who = hash_lookup (Who_Was, nick);
  252.     if (!who)
  253.     {
  254.     send_cmd (con, MSG_SERVER_NOSUCH, "who was failed: %s: no info",
  255.           nick);
  256.     return;
  257.     }
  258.     send_cmd (con, tag, "%s %u %s %u \"%s\"", who->nick, BSWAP32 (who->ip),
  259.         who->server, who->when, who->clientinfo);
  260. }
  261.  
  262. void
  263. free_whowas (whowas_t * who)
  264. {
  265.     if (who)
  266.     {
  267.     if (who->nick)
  268.         FREE (who->nick);
  269.     FREE (who);
  270.     }
  271. }
  272.  
  273. static void
  274. expire_whowas_cb (whowas_t * who, void *unused)
  275. {
  276.     (void) unused;
  277.     if (global.current_time - who->when >= Who_Was_Time)
  278.     {
  279.     /* entry is old, remove it */
  280.     hash_remove (Who_Was, who->nick);
  281.     }
  282. }
  283.  
  284. void
  285. expire_whowas (void)
  286. {
  287.     log ("expire_whowas: expiring old info");
  288.     hash_foreach (Who_Was, (hash_callback_t) expire_whowas_cb, 0);
  289.     log ("expire_whowas: %d nicks in the cache", Who_Was->dbsize);
  290.  
  291.     /* not really any better place to do this, so put it here for now */
  292.     cleanup_ip_info ();
  293. }
  294.